home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / devel / lang / forth / pfe-0.000 / pfe-0 / pfe-0.9.13 / src / signals.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-17  |  9.5 KB  |  418 lines

  1. /*
  2.  * This file is part of the portable Forth environment written in ANSI C.
  3.  * Copyright (C) 1995  Dirk Uwe Zoller
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Library General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13.  * See the GNU Library General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Library General Public
  16.  * License along with this library; if not, write to the Free
  17.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  * This file is version 0.9.13 of 17-July-95
  20.  * Check for the latest version of this package via anonymous ftp at
  21.  *    roxi.rz.fht-mannheim.de:/pub/languages/forth/pfe-VERSION.tar.gz
  22.  * or    sunsite.unc.edu:/pub/languages/forth/pfe-VERSION.tar.gz
  23.  * or    ftp.cygnus.com:/pub/forth/pfe-VERSION.tar.gz
  24.  *
  25.  * Please direct any comments via internet to
  26.  *    duz@roxi.rz.fht-mannheim.de.
  27.  * Thank You.
  28.  */
  29. /*
  30.  * signals.c --- Handle signals.
  31.  * (duz 25Apr94)
  32.  */
  33.  
  34. #include "forth.h"
  35. #include "support.h"
  36. #include "compiler.h"
  37. #include "term.h"
  38.  
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <float.h>
  42. #include <signal.h>
  43.  
  44. #include "nonansi.h"
  45. #include "missing.h"
  46.  
  47. typedef void (*SigHdl) (int);    /* signal handler function type */
  48.  
  49. enum                /* Classification of signals: The */
  50.   {                /* signal class is either a THROW code or: */
  51.     Fatal,            /*   pfe terminates if such a signal arrives */
  52.     Abort,            /*   executes ABORT" */
  53.     Chandled,            /*   handled by C code, e.g. stop/continue */
  54.     Default            /*   left alone by pfe, cannot be caught */
  55.   };
  56.  
  57. typedef struct            /* all we need to know about a signal */
  58.   {
  59.     short sig;            /* the signal */
  60.     short cLass;        /* a classification */
  61.     char *name;            /* the name of the signal */
  62. #ifndef HAVE_SYS_SIGLIST
  63.     char *msg;            /* a textual signal description */
  64. #endif
  65.     SigHdl old;            /* state of signal before we took it */
  66.     Xt hdl;            /* a forth word to handle the signal */
  67.   }
  68. Siginfo;
  69.  
  70. #ifdef OLDCPP
  71. #ifdef HAVE_SYS_SIGLIST
  72. #define SIG(NM,CL,MSG)        { NM, CL, "NM", SIG_DFL }
  73. #else
  74. #define SIG(NM,CL,MSG)        { NM, CL, "NM", MSG, SIG_DFL }
  75. #endif
  76. #else
  77. #ifdef HAVE_SYS_SIGLIST
  78. #define SIG(NM,CL,MSG)        { NM, CL, #NM, SIG_DFL }
  79. #else
  80. #define SIG(NM,CL,MSG)        { NM, CL, #NM, MSG, SIG_DFL }
  81. #endif
  82. #endif
  83.  
  84. /*
  85.  * With the means of the above structures and classifications we
  86.  * describe a lot of signals to pfe conditionally. Fine if a system
  87.  * has a signal. If not it's just as well.
  88.  */
  89.  
  90. static Siginfo siginfo[] =
  91. {
  92.  
  93. /*
  94.  * These are described in W.R.Stevens'
  95.  * "Advanced Programming in the UNIX Environment"
  96.  */
  97. #ifdef SIGABRT
  98.   SIG (SIGABRT, Fatal, "abnormal termination (abort)"),
  99. #endif
  100. #ifdef SIGALRM
  101.   SIG (SIGALRM, Abort, "time out (alarm)"),
  102. #endif
  103. #ifdef SIGBUS
  104.   SIG (SIGBUS, THROW_ADDRESS_ALIGNMENT, NULL),
  105. #endif
  106. #ifdef SIGCHLD
  107.   SIG (SIGCHLD, Default, "change in status of child"),
  108. #endif
  109. #ifdef SIGCONT
  110.   SIG (SIGCONT, Default, "continue stopped process"),
  111. #endif
  112. #ifdef SIGEMT
  113.   SIG (SIGEMT, Abort, "hardware fault (EMT)"),
  114. #endif
  115. #ifdef SIGFPE
  116.   SIG (SIGFPE, THROW_FLOATING_POINT, NULL),
  117. #endif
  118. #ifdef SIGHUP
  119.   SIG (SIGHUP, Fatal, "hangup"),
  120. #endif
  121. #ifdef SIGILL
  122.   SIG (SIGILL, Abort, "illegal hardware instruction"),
  123. #endif
  124. #ifdef SIGINFO
  125.   SIG (SIGINFO, Default, "status request from keyboard"),
  126. #endif
  127. #ifdef SIGINT
  128.   SIG (SIGINT, THROW_USER_INTERRUPT, NULL),
  129. #endif
  130. #ifdef SIGIO
  131.   SIG (SIGIO, Default, "asynchronous io"),
  132. #endif
  133. #ifdef SIGIOT
  134.   SIG (SIGIOT, Abort, "hardware fault (IOT)"),
  135. #endif
  136. #ifdef SIGKILL
  137.   SIG (SIGKILL, Default, "kill"),
  138. #endif
  139. #ifdef SIGPIPE
  140.   SIG (SIGPIPE, Fatal, "write to pipe with no readers"),
  141. #endif
  142. #ifdef SIGPOLL
  143.   SIG (SIGPOLL, Abort, "pollable event (poll)"),
  144. #endif
  145. #ifdef SIGPROF
  146.   SIG (SIGPROF, Abort, "profiling time alarm (setitimer)"),
  147. #endif
  148. #ifdef SIGPWR
  149.   SIG (SIGPWR, Default, "power fail/restart"),
  150. #endif
  151. #ifdef SIGQUIT
  152.   SIG (SIGQUIT, Fatal, "terminal quit key"),
  153. #endif
  154. #ifdef SIGSEGV
  155.   SIG (SIGSEGV, THROW_INVALID_MEMORY, NULL),
  156. #endif
  157. #ifdef SIGSTOP
  158.   SIG (SIGSTOP, Default, "stop"),
  159. #endif
  160. #ifdef SIGSYS
  161.   SIG (SIGSYS, Abort, "invalid system call"),
  162. #endif
  163. #ifdef SIGTERM
  164.   SIG (SIGTERM, Fatal, "terminated"),
  165. #endif
  166. #ifdef SIGTRAP
  167.   SIG (SIGTRAP, Abort, "hardware fault (trace trap)"),
  168. #endif
  169. #ifdef SIGTSTP
  170.   SIG (SIGTSTP, Chandled, "terminal stop character"),
  171. #endif
  172. #ifdef SIGTTIN
  173.   SIG (SIGTTIN, Chandled, "background read from control tty"),
  174. #endif
  175. #ifdef SIGTTOU
  176.   SIG (SIGTTOU, Chandled, "background write to control tty"),
  177. #endif
  178. #ifdef SIGURG
  179.   SIG (SIGURG, Abort, "urgent condition"),
  180. #endif
  181. #ifdef SIGUSR1
  182.   SIG (SIGUSR1, Abort, "user defined signal 1"),
  183. #endif
  184. #ifdef SIGUSR2
  185.   SIG (SIGUSR2, Abort, "user defined signal 2"),
  186. #endif
  187. #ifdef SIGVTALRM
  188.   SIG (SIGVTALRM, Abort, "virtual time alarm (setitimer)"),
  189. #endif
  190. #ifdef SIGWINCH
  191.   SIG (SIGWINCH, Chandled, "terminal window size change"),
  192. #endif
  193. #ifdef SIGXCPU
  194.   SIG (SIGXCPU, Fatal, "CPU limit exceeded"),
  195. #endif
  196. #ifdef SIGXFSZ
  197.   SIG (SIGXFSZ, Abort, "file size limit exceeded"),
  198. #endif
  199.  
  200.   /*
  201.    * Signals specific to certain systems.
  202.    */
  203. #ifdef SIGSTKFLT        /* Linux */
  204.   SIG (SIGSTKFLT, Abort, "SIGSTKFLT"),
  205. #endif
  206.  
  207. #ifdef SIGBREAK            /* EMX, Watcom */
  208.   SIG (SIGBREAK, THROW_USER_INTERRUPT, NULL),
  209. #endif
  210.  
  211. #ifdef SIGMSG            /* AIX 3.2 */
  212.   SIG (SIGMSG, Default, "input data is in the HFT ring buffer"),
  213. #endif
  214. #ifdef SIGDANGER
  215.   SIG (SIGDANGER, Default, "system crash imminent; free up some page space"),
  216. #endif
  217. #ifdef SIGMIGRATE
  218.   SIG (SIGMIGRATE, Default, "migrate process (see TCF)"),
  219. #endif
  220. #ifdef SIGPRE
  221.   SIG (SIGPRE, Default, "programming exception"),
  222. #endif
  223. #ifdef SIGVIRT
  224.   SIG (SIGVIRT, Default, "AIX virtual time alarm"),
  225. #endif
  226. #ifdef SIGGRANT
  227.   SIG (SIGGRANT, Default, "HFT monitor mode granted"),
  228. #endif
  229. #ifdef SIGRETRACT
  230.   SIG (SIGRETRACT, Default, "HFT monitor mode should be relinguished"),
  231. #endif
  232. #ifdef SIGSOUND
  233.   SIG (SIGSOUND, Default, "HFT sound control has completed"),
  234. #endif
  235. #ifdef SIGSAK
  236.   SIG (SIGSAK, Default, "secure attention key"),
  237. #endif
  238. };
  239.  
  240. static int
  241. getinfo (int sig)
  242. {
  243.   int i;
  244.  
  245.   for (i = 0; i < DIM (siginfo); i++)
  246.     if (siginfo[i].sig == sig)
  247.       return i;
  248.  
  249.   tHrow (THROW_ARG_TYPE);
  250.   return i;
  251. }
  252.  
  253. static void
  254. sig_handler (int sig)        /* Signal handler for all signals */
  255. {
  256.   Siginfo *s;
  257.   const char *msg;
  258.  
  259. #if !KEEPS_SIGNALS
  260.   signal (sig, sig_handler);    /* reinstall handler */
  261. #endif
  262. #if defined EMX || defined WC_OS2V2
  263.   signal (sig, SIG_ACK);    /* OS/2: acknowledge signal */
  264. #endif
  265. #if defined EMX
  266.   _control87 (EM_DENORMAL | EM_INEXACT, MCW_EM);
  267. #endif
  268.  
  269.   s = &siginfo[getinfo (sig)];
  270.   if (s->hdl)
  271.     call_forth (s->hdl);    /* a forth-handled signal */
  272.   else
  273.     {
  274. #ifdef HAVE_SYS_SIGLIST
  275.       msg = sys_siglist[sig];
  276. #else
  277.       msg = s->msg;
  278. #endif
  279.       switch (s->cLass)
  280.     {
  281.     default:        /* an ANSI-Forth defined condition */
  282.       tHrow (s->cLass);
  283.     case Abort:        /* another catchable signal */
  284.       tHrow (-2, msg, strlen (msg));
  285.     case Fatal:        /* a signal that kills us */
  286.       fatal ("got signal %s, %s", s->name, msg);
  287.       eXit (1);
  288.     }
  289.     }
  290. }
  291.  
  292. /*
  293.  * Actions to take when job control interferes or on window size change:
  294.  */
  295.  
  296. #ifdef SIGTSTP
  297. static void
  298. stop_hdl (int sig)
  299. {
  300. #if !KEEPS_SIGNALS
  301.   signal (sig, stop_hdl);
  302. #endif
  303.   on_stop ();
  304.   swap_signals ();
  305. #if _BSD
  306.   kill (getpid (), SIGSTOP);
  307. #else
  308.   raise (SIGTSTP);
  309. #endif
  310.   swap_signals ();
  311.   on_continue ();
  312. }
  313. #endif
  314.  
  315. #ifdef SIGWINCH
  316. static void
  317. winchg_hdl (int sig)
  318. {
  319. #if !KEEPS_SIGNALS
  320.   signal (sig, winchg_hdl);
  321. #endif
  322.   on_winchg ();
  323. }
  324. #endif
  325.  
  326. /*
  327.  * install all signal handlers:
  328.  */
  329.  
  330. void
  331. install_signal_handlers (void)
  332. {
  333.   int i, j;
  334.  
  335.   for (i = 0; i < DIM (siginfo); i++)
  336.     {
  337.       /* some systems may have more than one name for the same signal,
  338.        * take care not to install it twice: */
  339.       for (j = 0; j < i; j++)
  340.     if (siginfo[i].sig == siginfo[j].sig)
  341.       goto cont;
  342.       switch (siginfo[i].cLass)
  343.     {
  344.     default:
  345.       siginfo[i].old = signal (siginfo[i].sig, sig_handler);
  346.     case Chandled:
  347.     case Default:;
  348.     }
  349.     cont:;
  350.     }
  351. #ifdef SIGTSTP
  352.   if (signal (SIGTSTP, SIG_IGN) == SIG_DFL)
  353.     {
  354.       signal (SIGTSTP, stop_hdl);
  355.       siginfo[getinfo (SIGTSTP)].old = SIG_DFL;
  356.       siginfo[getinfo (SIGTTIN)].old = signal (SIGTTIN, stop_hdl);
  357.       siginfo[getinfo (SIGTTOU)].old = signal (SIGTTOU, stop_hdl);
  358.     }
  359. #endif
  360. #ifdef SIGWINCH
  361. #ifdef KEEPS_SIGNALS
  362.   signal (SIGWINCH, winchg_hdl);
  363. #endif
  364.   winchg_hdl (SIGWINCH);
  365. #endif
  366. }
  367.  
  368. void
  369. swap_signals (void)
  370. /* switch between pfe setting of signals and state before */
  371. {
  372.   int i;
  373.  
  374.   for (i = 0; i < DIM (siginfo); i++)
  375.     if (siginfo[i].cLass != Default || siginfo[i].hdl)
  376.       siginfo[i].old = signal (siginfo[i].sig, siginfo[i].old);
  377. }
  378.  
  379. Xt
  380. forth_signal (int sig, Xt xt)
  381. /*
  382.  * xt != NULL: install forth word as signal handler for signal
  383.  * xt == NULL: install pfe default signal handler for signal
  384.  */
  385. {
  386.   int i = getinfo (sig);
  387.   Xt old;
  388.  
  389.   old = siginfo[i].hdl;
  390.   siginfo[i].hdl = xt;
  391.  
  392.   if (siginfo[i].cLass == Default)
  393.     if (xt == NULL)
  394.       siginfo[i].old = signal (sig, siginfo[i].old);
  395.     else
  396.       siginfo[i].old = signal (sig, sig_handler);
  397.  
  398.   return old;
  399. }
  400.  
  401. void
  402. load_signals (Wordl *wid)
  403. /*
  404.  * Load constants for each signal found into the dictionary.
  405.  */
  406. {
  407.   Siginfo *s;
  408.   char *nfa;
  409.   Head *h;
  410.  
  411.   for (s = siginfo; s < siginfo + DIM (siginfo); s++)
  412.     {
  413.       h = make_head (s->name, strlen (s->name), &nfa, wid);
  414.       h->cfa = constant_runtime;
  415.       COMMA (s->sig);
  416.     }
  417. }
  418.